package de.mnit.basis.swt.grafik;

import java.io.File;
import java.io.InputStream;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Display;

import de.mnit.basis.fehler.Fehler;
import de.mnit.basis.fehler.system.F_Sys_Datei;
import de.mnit.basis.grafik.konstant.DATEIFORMAT_BILD;
import de.mnit.basis.swt.grafik.icon.Icon;
import de.mnit.basis.swt.grafik.icon.S_HatIcon;
import de.mnit.basis.swt.statisch.FarbManager;
import de.mnit.basis.sys.datei.S_Datei;
import de.mnit.basis.sys.datei.S_Ordner;

/**
 * @author Michael Nitsche
 */
public class Bild_SWT implements S_Bild_SWT {

	protected Image bild=null;


	public Bild_SWT(Object bild) throws F_Sys_Datei {
		Fehler.objekt.wenn_Null(bild);
		if(bild instanceof String[] && ((String[])bild).length>0)
			bild=((String[])bild)[0];

		if(bild instanceof Image)
			/*Ausgabe.warnung("Image wird direkt verwendet und ggf. von E_SWT_Bild freigegeben!"); TODO*/
			this.bild=(Image)bild;
		else if(bild instanceof ImageData)
			this.bild=new Image(Display.getDefault(), ((ImageData)bild));
		else if(bild instanceof InputStream)
			this.bild=iLaden((InputStream)bild);
		else if(bild instanceof Icon)
			this.bild=((Icon)bild).gBild().gImage(); //TODO Oder muß es kopiert werden???
		else if(bild instanceof S_Bild_SWT)
			this.bild=new Image(null,((S_Bild_SWT)bild).gImage(),SWT.IMAGE_COPY);
		else if(bild instanceof S_Datei) {
			Fehler.datei.wenn_Fehlt(bild); this.bild=iLaden(bild);
		}
		else if(bild instanceof Integer)
			this.bild=Display.getDefault().getSystemImage((Integer)bild);
		else if(bild instanceof String) {
			if(new File(""+bild).exists())
				this.bild=iLaden(bild);
			else
				throw Fehler.datei.da_Fehlt(bild);
		}
		else throw Fehler.objekt.da_KlasseUngueltig(bild);
	}

	public Bild_SWT(int dx, int dy, int rot, int gruen, int blau) {
		Fehler.zahl.wenn_Ausserhalb(1,3000,dx);
		Fehler.zahl.wenn_Ausserhalb(1,3000,dy);
		Fehler.zahl.wenn_Ausserhalb(0,255,rot);
		Fehler.zahl.wenn_Ausserhalb(0,255,gruen);
		Fehler.zahl.wenn_Ausserhalb(0,255,blau);

		Image image = new Image(null,dx,dy);
		GC gc = new GC(image);
		gc.setBackground(FarbManager.gFarbe(null,rot,gruen,blau));
		gc.fillRectangle(image.getBounds());
		gc.dispose();
		this.bild=image;
	}

	// NEU

	public static S_Bild_SWT neu(Object bild) throws F_Sys_Datei {
		return new Bild_SWT(bild);
	}

	public static S_Bild_SWT neu_Direkt(Object bild) throws F_Sys_Datei {
		Fehler.objekt.wenn_Null(bild);
		if(bild instanceof S_Bild_SWT)
			return ((S_Bild_SWT)bild);
		if(bild instanceof Icon)
			return ((Icon)bild).gBild();
		if(bild instanceof S_HatIcon)
			return ((S_HatIcon)bild).gIcon().gBild();
		return neu(bild);
	}

	public static S_Bild_SWT neu(int dx, int dy, int rot, int gruen, int blau) {
		return new Bild_SWT(dx,dy,rot,gruen,blau);
	}

	// LESEN

	public int gBreite() {
		return this.bild.getBounds().width;
	}

	public int gHoehe() {
		return this.bild.getBounds().height;
	}

	public Image gImage() {
		return this.bild;
	}

	public boolean gFreigegeben() {
		return bild.isDisposed();
	}

	public int gFarbBitsOriginal() {
		throw Fehler.objekt.da_ToDo();
	}

	// BEFEHLE

	public void freigeben() {
		this.bild.dispose();
	}

	public S_Bild_SWT kopie() {
		try {
			return Bild_SWT.neu(new Image(null, this.bild, SWT.IMAGE_COPY)); //beachte auch Konstruktor
		}
		catch(F_Sys_Datei e)   { throw Fehler.sonstige.da_Unmoeglich(e); }
	}

	public void speichern(String datei, DATEIFORMAT_BILD format)   {
	    Fehler.objekt.wenn_Null(datei);
	    int swt_format=-1;
//	    if(format==DATEIFORMAT_BILD.BMP)
//	    	swt_format=SWT.IMAGE_BMP; // FarbPalette wird falsch gespeichert
	    if(format==DATEIFORMAT_BILD.JPEG)
	    	swt_format=SWT.IMAGE_JPEG;
	    if(format==DATEIFORMAT_BILD.PNG)
	    	swt_format=SWT.IMAGE_PNG; // Seit 3.3 //TODO testen
	    if(format==DATEIFORMAT_BILD.GIF && this.bild.getImageData().depth ==8)
	    	swt_format=SWT.IMAGE_GIF; // Macht unter Linux Probleme wegen GTK 24Bit Palette > 8 Bit Gif
	    if(swt_format==-1)
	    	Fehler.objekt.da_HierUngueltig("DETAIL: Derzeit nicht unterstützter Bild-Typ!","TYP: "+format.name());

		ImageLoader loader = new ImageLoader();
		ImageData[] data=new ImageData[]{ this.bild.getImageData() };

		loader.data = data;
		loader.logicalScreenHeight = data[0].height;
		loader.logicalScreenWidth = data[0].width;
//		loader.backgroundPixel = 0;
//		loader.repeatCount = 0;

		loader.save(datei+"."+format.suffixStd, swt_format);
	}

	public void speichernJPEG(String datei, int qualitaet) {
	    Fehler.objekt.wenn_Null(datei);
	    Fehler.zahl.wenn_Ausserhalb(1,100,qualitaet);
	    Fehler.zahl.wenn_Nicht(75, qualitaet); //TODO Prüfen! Angeblich war früher nur 75 (Standard) möglich!
//		siehe: org.eclipse.swt.internal.image.JPEGFileFormat.encoderQFactor=75;

		ImageLoader loader = new ImageLoader();
		ImageData[] data=new ImageData[]{this.bild.getImageData()};
		loader.data = data;
		loader.logicalScreenHeight = data[0].height;
		loader.logicalScreenWidth = data[0].width;
		loader.save(datei+"."+DATEIFORMAT_BILD.JPEG.suffixStd, SWT.IMAGE_JPEG);
	}

	public S_Datei speichern(S_Ordner v, String name, DATEIFORMAT_BILD format) throws F_Sys_Datei {
		S_Datei erg=v.d(name,format.suffixStd);
		this.speichern(erg.gPfadKomplett(),format);
		return erg;
	}

	public void disabledImage() {
		Image temp = new Image(null, this.bild, SWT.IMAGE_GRAY);
//		Image temp = new Image(null, this.bild, SWT.IMAGE_DISABLE);
		ImageData data = temp.getImageData();
		int width = data.width;
		int height = data.height;
		for(int y=0;y<height;y++)
			for(int x=0;x<width;x++)
				data.setAlpha(x, y, data.getAlpha(x, y)/3); //Durch 4 ist zu hell und /2 ist zu dunkel. Und fix (-128) ist nicht schön
		//Die 3 Zeilen sind für Linux nicht nötig, aber funktioniert sonst in Win nicht:
		temp = new Image(null,data);
	    this.bild.dispose();
	    this.bild=temp;
	}

	// INTERN

	private Image iLaden(Object o) {
		//Viel langsamer als Image(null,o) das native Methoden nutzt, macht aber unter Win Probleme bei Transparenz!
		ImageLoader loader = new ImageLoader();
		ImageData[] data= o instanceof InputStream ? loader.load((InputStream)o) : loader.load(""+o);
		return new Image(null, data[0]);
	}

}
